[ARC082F]Sandglass

2020-03-10
Atcoder

题意

一个沙漏上下部分最大容量均为$X$,已知在$\{r_k\}$时刻把沙漏倒过来

$Q$个询问,每次询问若初始时上面部分有$a$,下半部分有$X-a$,时间为$t$时上半部分的含量

$n,Q\leq 10^5$

题解

其实就是一根折线,斜率为-1,0,1,范围在$[0,X]​$内,多次改变起点高度,问某处的值

如果$a_i\leq a_j$,那么当$t$相等时,前者的值必然不大于后者

这样就可以用起点为0和X的两条折线进行限制,维护两条折线即可

调试记录

nQ搞糊涂了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <cstdio>
#include <algorithm>
const int maxn = 1e5 + 5;
using namespace std;
struct QNode{
int t, a, res, id;
bool operator< (QNode x)const{
return t < x.t || (t == x.t && a < x.a);
}
}q[maxn]; int X, n, Q, r[maxn], opt = -1;
bool cmpid(QNode x, QNode y){
return x.id < y.id;
}
int main(){
scanf("%d%d", &X, &n); for (int i = 1; i <= n; i++) scanf("%d", r + i);
scanf("%d", &Q); for (int i = 1; i <= Q; i++) scanf("%d%d", &q[i].t, &q[i].a), q[i].id = i;
sort(q + 1, q + Q + 1);
int lr = 0, lq = 1, u = X, d = 0, S = 0;
while (lq <= Q){
if (r[lr + 1] < q[lq].t && lr < n){
++lr; int t = opt * (r[lr] - r[lr - 1]);
d = max(0, min(X, d + t));
u = max(0, min(X, u + t));
S += t; opt *= -1;
}
else{
q[lq].res = max(d, min(u, S + q[lq].a));
q[lq].res = min(X, max(0, q[lq].res + opt * (q[lq].t - r[lr])));
++lq;
}
} sort(q + 1, q + Q + 1, cmpid);
for (int i = 1; i <= Q; i++) printf("%d\n", q[i].res);
return 0;
}